package com.jhws.common.pay.service;

import com.jhws.business.customer.bo.PayCustomerSecret;
import com.jhws.business.customer.service.PayCustService;
import com.jhws.core.exception.BizException;
import com.jhws.util.*;
import com.jhws.common.pay.bo.PayConstants;
import com.jhws.util.security.MD5Util;
import com.jhws.util.net.JhHttpClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class WXPayService {
    @Resource
    PayCustService IPayCustService;
    @Resource
    RedisTemplate stringTemplate;
    /**
     * 生成32位随机数
     *
     * @return
     */
    public String genNonceStr() {
        return GetId.buildRandom(10) + "";
    }

    /**
     * 微信要求总金额必须是分，还不能带小数点
     *
     * @param totalFee
     * @return
     */
    public String genTotalFee(String totalFee) {
        //金额转化为分为单位
        float sessionmoney = Float.parseFloat(totalFee);
        String finalmoney = String.format("%.2f", sessionmoney);
        finalmoney = finalmoney.replace(".", "");
        return Integer.parseInt(finalmoney) + "";
    }

    /**
     * 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。
     */
    public String createSign(SortedMap<String, String> packageParams, String key, String charset) {
        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String k = (String) entry.getKey();
            String v = (String) entry.getValue();
            if (null != v && !"".equals(v) && !"sign".equals(k)
                    && !"key".equals(k)) {
                sb.append(k + "=" + v + "&");
            }
        }
        sb.append("key=" + key);
        System.out.println("md5 sb:" + sb);
        String sign = MD5Util.MD5Encode(sb.toString(), charset)
                .toUpperCase();
        System.out.println("packge签名:" + sign);
        return sign;

    }

    /**
     * 统一下单接口
     *
     * @param url
     * @param xml
     * @return
     * @throws Exception
     */
    public Map sendOrderRequest(String url, String xml) throws Exception {
        JhHttpClient httpClient = new JhHttpClient();
        String body = httpClient.post(url, xml);
        LogHelper.d(body);
        if (body.indexOf("FAIL") != -1) {
            return new HashMap();
        }
        Map map = XmlUtils.doXMLParse(body);
        return map;
    }

    /**
     * 公众号获取openId接口
     *
     * @param appId  公众号appId
     * @param secret 公众号的secret
     * @param code   网页授权拿到的code
     * @return openId
     */
    public String getOpenId(String appId, String secret, String code) {
        JhHttpClient httpClient = new JhHttpClient();
        String url = PayConstants.WeixinMchAccessTokenUrl + "?appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
        String ret = httpClient.get(url, null);
        LogHelper.d(ret);
        return jsonUtil.getKeyFromJsonObject(ret, "openid");
    }

    /**
     * 通过第三方平台获取授权appId的openId
     * @param appId
     * @return
     */
    public String getOpenIdBy3rd(String appId, String code) throws Exception{
        JhHttpClient httpClient = new JhHttpClient();
        String accessToken = get3rdComponentAccessToken(null);
        String url = PayConstants.WeixinUrl3rdGetOpenId + "?appid=" + appId  + "&code=" + code + "&grant_type=authorization_code"+"&component_appid="+PayConstants.Weixin3rdCommServiceAppId+
                "&component_access_token="+accessToken;
        String ret = httpClient.get(url, null);
        LogHelper.d(ret);
        return jsonUtil.getKeyFromJsonObject(ret, "openid");
    }

    /**
     * 获取appId
     *
     * @param customId
     * @return
     * @throws Exception
     */
    public String getAppId(Long customId) throws Exception {
        PayCustomerSecret payCustomerSecret = IPayCustService.findCustSecretByPayType(customId, PayConstants.PAY_TYPE_WEIXIN_H5);
        if (payCustomerSecret == null || StringUtils.isEmpty(payCustomerSecret.getAppId())) {
            throw new BizException("-1", "", "appId 不存在！！！");
        }
        return payCustomerSecret.getAppId();
    }

    /**
     * 通过appId获取微信支付地址
     *
     * @param appId
     * @return
     */
    public String getSubscriptionPayUrl(String appId) {
        return PayConstants.WeixinSubscriptionPayUrl + "?appid=" + appId + "&response_type=code&scope=snsapi_base&redirect_uri=";
    }

    /**
     * 获取微信支付地址
     *
     * @param customId
     * @return
     * @throws Exception
     */
    public String getSubscriptionPayUrl(Long customId) throws Exception {
        return getSubscriptionPayUrl(getAppId(customId));
    }


    public String get3rdComponentAccessToken(String tkt) throws Exception{
        ValueOperations valueOperations = stringTemplate.opsForValue();
        String accessToken = (String)valueOperations.get(PayConstants.REDIS_PAY_WEIXIN_3RD_ACCESS_TOKEN);
        if(accessToken != null)
            return accessToken;

        String ticket = tkt!=null?tkt:(String)valueOperations.get(PayConstants.REDIS_PAY_WEIXIN_3RD_VERIFY_TICKET);
        if(StringUtils.isEmpty(ticket))
            return null;
        JhHttpClient httpClient = new JhHttpClient();
        Map<String,String> dataMap = new HashMap();
        dataMap.put("component_appid",PayConstants.Weixin3rdCommServiceAppId);
        dataMap.put("component_appsecret",PayConstants.Weixin3rdCommServiceAppSecret);
        dataMap.put("component_verify_ticket",ticket);

        LogHelper.t("data post : "+GsonUtil.toJson(dataMap));
        String ret = httpClient.post(PayConstants.WeixinURLGetAccessToken,GsonUtil.toJson(dataMap));
        Map retMap = GsonUtil.toObject(ret,Map.class);
        accessToken = (String)retMap.get("component_access_token");
        LogHelper.d("ret: "+ret);

        Integer expireTime = ((Double)retMap.get("expires_in")).intValue();
        LogHelper.d("expireTime "+expireTime);

        if(StringUtils.isNotEmpty(accessToken))
            valueOperations.set(PayConstants.REDIS_PAY_WEIXIN_3RD_ACCESS_TOKEN,accessToken,expireTime - 300, TimeUnit.SECONDS);
        return accessToken;
    }

    public String get3rdPreAuthCode() throws Exception{
        String accessToken = get3rdComponentAccessToken(null);
        if(StringUtils.isEmpty(accessToken))
            return accessToken;

        JhHttpClient httpClient = new JhHttpClient();
        Map<String,String> dataMap = new HashMap();
        dataMap.put("component_appid",PayConstants.Weixin3rdCommServiceAppId);

        LogHelper.t("post : "+PayConstants.WeixinURLGetPreAuthCode + "?component_access_token="+accessToken+" data: "+GsonUtil.toJson(dataMap));
        return httpClient.post(PayConstants.WeixinURLGetPreAuthCode + "?component_access_token="+accessToken,GsonUtil.toJson(dataMap));
    }

    /**
     * 生成能兼容微信和支付宝的支付跳转链接
     * @param request
     * @param url
     * @param appId
     * @return
     */
    public String getCompatibleUrlForWxAndAlipay(HttpServletRequest request, String url,String appId){
        String baseUrl = request.getScheme() + "://" + request.getServerName();
        baseUrl += url;
        String ua = request.getHeader("user-agent").toLowerCase();
        if (ua.indexOf("micromessenger") > 0) {// 是微信浏览器
            return PayConstants.WeixinSubscriptionPayUrl+"?appid=" + appId + "&component_appid="+ PayConstants.Weixin3rdCommServiceAppId+"&response_type=code&scope=snsapi_base&redirect_uri=" + baseUrl;
        }
        return baseUrl;
    }
}
